﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Steema.TeeChart;
using AAA.TeeChart.Data;
using AAA.Meta.Chart.Data;
using Steema.TeeChart.Styles;
using AAA.Meta.Chart;
using System.Drawing;

namespace AAA.TeeChart
{
    public class TeeChartFormat
    {
        private LabelAlignmentEnum _enumLabelAlignment;
        private TChart _tChart;
        private Steema.TeeChart.Axis _custAxisBottom;
        private Steema.TeeChart.Axis _custAxisLeft;
        private Steema.TeeChart.Axis _custAxisRight;
        
        private Dictionary<string, SeriesFormat> _dicSeries;        
        private Dictionary<string, Color> _dicSeriesColor;
        private Dictionary<string, Color> _dicMarkColor;        
        private IDataSource _dataSource;

        private int _iXMin;
        private int _iXMax;
        private float _fYMin;
        private float _fYMax;
        private List<string> _lstActiveSeries;
        private ScaleTypeEnum _eScaleType;
        private bool _needShowMark;
        private string _strYAxisFormat;
        private BarData _baseSeriesData;                

        private bool _isMarkSeries;

        public Steema.TeeChart.Axis CustAxisBottom
        {
            get { return _custAxisBottom; }
            set { _custAxisBottom = value; }
        }

        public Steema.TeeChart.Axis CustAxisLeft
        {
            get { return _custAxisLeft; }
            set { _custAxisLeft = value; }
        }

        public Steema.TeeChart.Axis CustAxisRight
        {
            get { return _custAxisRight; }
            set { _custAxisRight = value; }
        }

        public bool IsMarkSeries
        {
            get { return _isMarkSeries; }
            set { _isMarkSeries = value; }
        }

        public BarData BaseSeriesData
        {
            get { return _baseSeriesData; }
            set { _baseSeriesData = value; }
        }


        public LabelAlignmentEnum LabelAlignment
        {
            get { return _enumLabelAlignment; }
            set { _enumLabelAlignment = value; }
        }

        public string YAxisFormat
        {
            get { return _strYAxisFormat; }
            set { _strYAxisFormat = value; }
        }

        public bool NeedShowMark
        {
            get { return _needShowMark; }
            set { _needShowMark = value; }
        }

        public ScaleTypeEnum ScaleType
        {
            get { return _eScaleType; }
            set { _eScaleType = value; }
        }
//        private int _iPointCount;
        
        public string DateTimeFormat
        {
            get 
                {
                    return _tChart.Axes.Bottom.Labels.DateTimeFormat; 
                }
            set 
                { 
                    _tChart.Axes.Bottom.Labels.DateTimeFormat = value;
                }
        }

        public int XMin
        {
            get { return _iXMin; }
            set 
            { 
                _iXMin = value;
                ResetXRange();
            }
        }

        public int XMax
        {
            get { return _iXMax; }
            set 
            { 
                _iXMax = value;
                ResetXRange();
            }
        }


        public float YMin
        {
            get { return _fYMin; }
            set { _fYMin = value; }
        }

        public float YMax
        {
            get { return _fYMax; }
            set { _fYMax = value; }
        }

/*
        public int PointCount
        {
            get { return _iPointCount; }
            set { _iPointCount = value; }
        }
*/
        public IDataSource DataSource
        {
            get { return _dataSource; }
            set { _dataSource = value; }
        }

        public TeeChartFormat(TChart tChart)
        {
            _tChart = tChart;
            _dicSeries = new Dictionary<string, SeriesFormat>();
            _dicSeriesColor = new Dictionary<string, Color>();
            _dicMarkColor = new Dictionary<string, Color>();

            _dicMarkColor.Add("-1.00", Color.Green);
            _dicMarkColor.Add("0.00", Color.Transparent);
            _dicMarkColor.Add("1.00", Color.Red);

            FormatChart();
        }

        public void SetAxisVisible(PositionEnum ePosition, bool isVisible)
        {
            switch (ePosition)
            {
                case PositionEnum.Top:
                    _tChart.Axes.Top.Visible = isVisible;
                    break;
                case PositionEnum.Bottom:
                    _tChart.Axes.Bottom.Visible = isVisible;
                    break;
                case PositionEnum.Left:
                    _tChart.Axes.Left.Visible = isVisible;
                    break;
                case PositionEnum.Right:
                    _tChart.Axes.Right.Visible = isVisible;
                    break;
            }
        }

        public void SetChartTitle(string strTitle)
        {
            _tChart.Header.Text = strTitle;                    
        }

        public void SetMargin(PositionEnum ePosition, int iMargin)
        {
            switch (ePosition)
            {
                case PositionEnum.Left:
                    _tChart.Panel.MarginLeft = iMargin;
                    break;
                case PositionEnum.Right:
                    _tChart.Panel.MarginRight = iMargin;
                    break;
                case PositionEnum.Bottom:
                    _tChart.Panel.MarginBottom = iMargin;
                    break;
            }
        }        

        private void FormatChart()
        {
            _tChart.BackColor = Color.Black;
            _tChart.Aspect.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            _tChart.Aspect.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            _tChart.Aspect.View3D = false;
            _tChart.AutoRepaint = true;
            _tChart.Panel.MarginUnits = PanelMarginUnits.Pixels;
            //_tChart.Panel.MarginTop = 5;
            _tChart.Panel.MarginBottom = 40;
            _tChart.Panel.MarginLeft = 5;
            _tChart.Panel.MarginRight = 100;
            _tChart.Legend.Visible = false;
            _tChart.Axes.Left.Automatic = true;
            _tChart.Axes.Right.Automatic = true;           
            _tChart.Axes.Bottom.Labels.DateTimeFormat = DateTimeFormat;

            _tChart.Axes.Top.Visible = false;
            _tChart.Axes.Bottom.Visible = false;
            _tChart.Axes.Left.Visible = false;
            _tChart.Axes.Right.Visible = false;

            if (!IsMarkSeries)
            {
                _custAxisBottom = new Axis(true, false, _tChart.Chart);
                _custAxisLeft = new Axis(false, false, _tChart.Chart);
                _custAxisRight = new Axis(false, true, _tChart.Chart);

                _tChart.Axes.Custom.Add(_custAxisBottom);
                _tChart.Axes.Custom.Add(_custAxisLeft);
                _tChart.Axes.Custom.Add(_custAxisRight);

                //            _custAxisBottom.Automatic = false;
                //            _custAxisBottom.AutomaticMaximum = false;
                //            _custAxisBottom.AutomaticMinimum = false;
                _custAxisBottom.AxisPen.Color = System.Drawing.Color.Black;
                _custAxisBottom.AxisPen.Width = 1;
                _custAxisBottom.Grid.Color = System.Drawing.Color.FromArgb(128, 128, 128);
                _custAxisBottom.Grid.Transparency = 50;
                //            _custAxisBottom.Labels.ValueFormat = DateTimeFormat;
                //            _custAxisBottom.Labels.DateTimeFormat = DateTimeFormat;
                _custAxisBottom.Labels.Font.Brush.Color = System.Drawing.Color.Black;
                //            _custAxisBottom.Maximum = 39300.583333333336;
                //            _custAxisBottom.Minimum = 39300.375;
                _custAxisBottom.MinorTickCount = 10;
                _custAxisBottom.PositionUnits = Steema.TeeChart.PositionUnits.Pixels;
                _custAxisBottom.Title.Visible = false;
                _custAxisBottom.Visible = true;

                //            _custAxisLeft.Automatic = false;
                //            _custAxisLeft.AutomaticMaximum = false;
                //            _custAxisLeft.AutomaticMinimum = false;

                _custAxisLeft.AxisPen.Color = System.Drawing.Color.Black;
                _custAxisLeft.AxisPen.Width = 1;
                _custAxisLeft.Grid.Color = System.Drawing.Color.FromArgb(128, 128, 128);
                _custAxisLeft.Grid.DrawEvery = 2;
                _custAxisLeft.Grid.Transparency = 50;
                _custAxisLeft.Labels.Font.Brush.Color = System.Drawing.Color.Black;
                _custAxisLeft.Labels.ValueFormat = "0.00";
                _custAxisLeft.MinorTickCount = 1;
                _custAxisLeft.PositionUnits = Steema.TeeChart.PositionUnits.Pixels;
                _custAxisLeft.Title.Visible = false;
                _custAxisLeft.Visible = false;

                //            _custAxisRight.Automatic = false;
                //            _custAxisRight.AutomaticMaximum = false;
                //            _custAxisRight.AutomaticMinimum = false;
                _custAxisRight.AxisPen.Color = System.Drawing.Color.Black;
                _custAxisRight.AxisPen.Width = 1;
                _custAxisRight.Grid.Visible = false;
                _custAxisRight.Labels.Font.Brush.Color = System.Drawing.Color.Black;
                _custAxisRight.Labels.ValueFormat = "0.00";
                _custAxisRight.MinorTickCount = 1;
                _custAxisRight.PositionUnits = Steema.TeeChart.PositionUnits.Pixels;
                _custAxisRight.Title.Visible = false;
                _custAxisRight.Visible = true;
            }
        }

        public void AddSeries(string strSeriesName, SeriesFormat seriesFormat)
        {
            AddSeries(strSeriesName, seriesFormat, Color.Yellow);
        }

        public void AddSeries(string strSeriesName, SeriesFormat seriesFormat, Color cSeriesColor)
        {
            if (_dicSeries.ContainsKey(strSeriesName) == false)
                _dicSeries.Add(strSeriesName, seriesFormat);

            if (_dicSeriesColor.ContainsKey(strSeriesName) == false)
                _dicSeriesColor.Add(strSeriesName, cSeriesColor);
        }

        public void RemoveSeries(string strSeriesName)
        {
            if (_dicSeries.ContainsKey(strSeriesName))
                _dicSeries.Remove(strSeriesName);
        }

        public SeriesFormat GetSeriesFormat(string strSeriesName)
        {
            return _dicSeries.ContainsKey(strSeriesName) ? _dicSeries[strSeriesName] : null;
        }

        private void ResetXRange()
        {
            try
            {
                
                //_tChart.Axes.Bottom.SetMinMax(XMin, XMax);
                _custAxisBottom.SetMinMax(XMin, XMax);

                if (XMin > XMax)
                    return;

                BarData barData;
                float fMax = -float.MaxValue;
                float fMin = float.MaxValue;
                float fPad;
                int iMaxPoint;
                int iMinPoint;

                if (IsMarkSeries == false)
                {
                    foreach (string strSeriesName in _dicSeries.Keys)
                    {
                        if (_lstActiveSeries != null)
                            if (_lstActiveSeries.IndexOf(strSeriesName) < 0)
                                continue;
                        barData = DataSource.GetBarData(strSeriesName);
                        for (int i = XMin; i <= XMax; i++)
                        {
                            if (float.IsNaN(barData.High(i)) || float.IsNaN(barData.Low(i)))
                                continue;

                            if (barData.High(i) > fMax)
                            {
                                fMax = barData.High(i);
                                iMaxPoint = i;
                            }

                            if (barData.Low(i) < fMin)
                            {
                                fMin = barData.Low(i);
                                iMinPoint = i;
                            }
                        }
                    }
                    fPad = (float)((fMax - fMin) * 0.1);

                    switch (_eScaleType)
                    {
                        case ScaleTypeEnum.UserDefine:
                            fMax = YMax;
                            fMin = YMin;
                            break;
                        case ScaleTypeEnum.Screen:
                            fMin -= fPad;
                            fMax += fPad;
                            break;
                        case ScaleTypeEnum.Volume:
                            fMin = 0;
                            fMax += fPad;
                            break;
                    }
                    //_tChart.Axes.Left.SetMinMax(fMin, fMax);
                    _custAxisRight.SetMinMax(fMin, fMax);
                }
                if (NeedShowMark)
                {

                }

                
                //_tChart.Refresh();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message + "," + ex.StackTrace);
            }
        }

        public void DrawChart()
        {
            DrawChart(null);
        }
        public void DrawChart(List<string> lstActiveSeries)
        {
            string strSeriesName;
            BarData barData;
            SeriesFormat seriesFormat;
            Line line;
            Bar bar;
            Histogram histogram;
            Volume volume;
            Candle candleStick;
            Color cMark;

            StringList labels = new StringList(10);
            try
            {
                try
                {
                    if (!IsMarkSeries)
                    {
                        _custAxisLeft.Labels.ValueFormat = YAxisFormat;
                        _custAxisRight.Labels.ValueFormat = YAxisFormat;
                    }
                }
                catch (Exception ex)
                {                    
                }

                _lstActiveSeries = lstActiveSeries;
                if(!IsMarkSeries)
                    _tChart.Series.RemoveAllSeries();
                for (int i = 0; i < DataSource.GetSeriesName().Count; i++)
                {
                    strSeriesName = DataSource.GetSeriesName()[i];

                    if (lstActiveSeries != null)
                        if (lstActiveSeries.IndexOf(strSeriesName) < 0)
                            continue;

                    barData = DataSource.GetBarData(strSeriesName);
                    seriesFormat = GetSeriesFormat(strSeriesName);                    

                    switch (seriesFormat.SeriesStyle)
                    {
                        case AAA.Meta.Chart.ChartStyleEnum.Marks:
                            line = new Steema.TeeChart.Styles.Line();
                            line.TreatNulls = TreatNullsStyle.DoNotPaint;                            
                            line.ColorEach = true;
                            line.Pointer.Style = PointerStyles.Triangle;
                            line.Pointer.Visible = true;
                            line.LinePen.Visible = false;
                            
                            for (int j = 0; j < barData.GetLength(); j++)
                            {
                                if (float.IsNaN(barData.Volume(j)))
                                {
                                    cMark = Color.Transparent;
                                }
                                else
                                {
                                    if(_dicMarkColor.ContainsKey(barData.Volume(j).ToString("0.00")) == false)
                                    {
                                        cMark = Color.Transparent;
                                    }
                                    else
                                    {
                                        cMark = _dicMarkColor[barData.Volume(j).ToString("0.00")];
                                    }
                                }


                                line.Add(j, float.IsNaN(barData.Close(j)) ? (float?)null : (float?)barData.Close(j),
                                            cMark);

                                if (i == 0)
                                    labels.Add(barData.DateTime(j).ToString(DateTimeFormat));
                            }
                            if (i == 0)
                                line.Labels = labels;
                            line.XValues.DateTime = false;
                            line.CustomHorizAxis = _custAxisBottom;
                            line.CustomVertAxis = _custAxisRight;                            
                            _tChart.Series.Add(line);
                            break;

                        case AAA.Meta.Chart.ChartStyleEnum.Line:
                            line = new Steema.TeeChart.Styles.Line();
                            line.TreatNulls = TreatNullsStyle.DoNotPaint;
                            //line.Color = _dicSeriesColor[strSeriesName];
                            for (int j = 0; j < barData.GetLength(); j++)
                            {
                                //line.Add(barData.DateTime(j), barData.Close(j));

                                line.Add(j, float.IsNaN(barData.Close(j)) ? (float?) null : (float?)barData.Close(j));
                                if (i == 0)
                                    labels.Add(barData.DateTime(j).ToString(DateTimeFormat));
                            }
                            if (i == 0)
                                line.Labels = labels;
                            line.XValues.DateTime = false;
                            line.CustomHorizAxis = _custAxisBottom;
                            line.CustomVertAxis = _custAxisRight;
                            //                        line.GetHorizAxis.Labels.Angle = 90;                        
                            _tChart.Series.Add(line);
                            break;

                        case AAA.Meta.Chart.ChartStyleEnum.Volume:
                            volume = new Steema.TeeChart.Styles.Volume();
                            volume.TreatNulls = TreatNullsStyle.DoNotPaint;
                            volume.Brush.Color = _dicSeriesColor[strSeriesName];
                            volume.LinePen.Color = _dicSeriesColor[strSeriesName];
                            volume.LinePen.Width = 5;
                            
                            for (int j = 0; j < barData.GetLength(); j++)
                            {
                                //histogram.Add(barData.DateTime(j), barData.Close(j));
                                volume.Add(j, float.IsNaN(barData.Close(j)) ? (float?)null : (float?)barData.Close(j));
                                if (i == 0)
                                    labels.Add(barData.DateTime(j).ToString(DateTimeFormat));
                            }
                            if (i == 0)
                                volume.Labels = labels;
                            volume.XValues.DateTime = false;
                            volume.CustomHorizAxis = _custAxisBottom;
                            volume.CustomVertAxis = _custAxisRight;
                            //                        histogram.GetHorizAxis.Labels.Angle = 90;
                            _tChart.Series.Add(volume);
                            break;

                        case AAA.Meta.Chart.ChartStyleEnum.Histogram:
                            histogram = new Steema.TeeChart.Styles.Histogram();
                            histogram.TreatNulls = TreatNullsStyle.DoNotPaint;
                            histogram.Brush.Color = Color.Yellow;//_dicSeriesColor[strSeriesName];
                            histogram.LinePen.Color = Color.Black;//_dicSeriesColor[strSeriesName];
                            for (int j = 0; j < barData.GetLength(); j++)
                            {
                                //histogram.Add(barData.DateTime(j), barData.Close(j));
                                histogram.Add(j, float.IsNaN(barData.Close(j)) ? (float?)null : (float?)barData.Close(j));
                                if (i == 0)
                                    labels.Add(barData.DateTime(j).ToString(DateTimeFormat));
                            }
                            if (i == 0)
                                histogram.Labels = labels;
                            histogram.XValues.DateTime = false;
                            histogram.CustomHorizAxis = _custAxisBottom;
                            histogram.CustomVertAxis = _custAxisRight;
                            //                        histogram.GetHorizAxis.Labels.Angle = 90;
                            _tChart.Series.Add(histogram);
                            break;
                        case AAA.Meta.Chart.ChartStyleEnum.Bar:
                            bar = new Steema.TeeChart.Styles.Bar();
                            
                            //bar.Brush.Color = _dicSeriesColor[strSeriesName];
                            //bar.Pen.Color = _dicSeriesColor[strSeriesName];         
                            bar.ColorEach = true;
                            bar.BarWidthPercent = 100;
                            for (int j = 0; j < barData.GetLength(); j++)
                            {
/*
                                bar.Add(j, float.IsNaN(barData.Close(j)) ? (float?)null : (float?)barData.Close(j), 
                                        j == 0 
                                            ? Color.White
                                            : (barData.Close(j) > barData.Close(j - 1)) 
                                                ? Color.Red
                                                : (barData.Close(j) == barData.Close(j - 1)) 
                                                    ?   Color.White
                                                    :   Color.Green);
 */

                                bar.Add(j, float.IsNaN(barData.Close(j)) ? (float?)null : (float?)barData.Close(j),
                                        BaseSeriesData == null
                                            ? Color.Yellow
                                            : (BaseSeriesData.Close(j) > BaseSeriesData.Open(j))
                                                ? Color.Red
                                                : (BaseSeriesData.Close(j) == BaseSeriesData.Open(j))
                                                    ? Color.Black
                                                    : Color.Green);
                                if (i == 0)
                                    labels.Add(barData.DateTime(j).ToString(DateTimeFormat));

                            }
                            if (i == 0)
                                bar.Labels = labels;

                            bar.Marks.Visible = false;
                            bar.XValues.DateTime = false;
                            bar.CustomHorizAxis = _custAxisBottom;
                            bar.CustomVertAxis = _custAxisRight;
                            //                        histogram.GetHorizAxis.Labels.Angle = 90;
                            _tChart.Series.Add(bar);
                            break;

                        case AAA.Meta.Chart.ChartStyleEnum.CandleStick:
                            candleStick = new Steema.TeeChart.Styles.Candle();
                            candleStick.TreatNulls = TreatNullsStyle.DoNotPaint;
                            candleStick.UpCloseColor = Color.Red;
                            candleStick.DownCloseColor = Color.Green;
                            
                            for (int j = 0; j < barData.GetLength(); j++)
                            {
                                /*
                                                            candleStick.Add(barData.DateTime(j),
                                                                            barData.Open(j),
                                                                            barData.High(j),
                                                                            barData.Low(j),
                                                                            barData.Close(j));
                                 */                                
                                candleStick.Add(j,
                                                float.IsNaN(barData.Open(j)) ? barData.Close(j - 1) : barData.Open(j),
                                                float.IsNaN(barData.High(j)) ? barData.Close(j - 1) : barData.High(j),
                                                float.IsNaN(barData.Low(j)) ? barData.Close(j - 1) : barData.Low(j),
                                                float.IsNaN(barData.Close(j)) ? barData.Close(j - 1) : barData.Close(j));
                                if (i == 0)
                                    labels.Add(barData.DateTime(j).ToString(DateTimeFormat));
                            }
                            if (i == 0)
                                candleStick.Labels = labels;
                            candleStick.XValues.DateTime = false;
                            candleStick.CustomHorizAxis = _custAxisBottom;
                            candleStick.CustomVertAxis = _custAxisRight;
                            //                        candleStick.GetHorizAxis.Labels.Angle = 90;
                            _tChart.Series.Add(candleStick);
                            break;
                    }
                }
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message + "," + ex.StackTrace);
            }
        }
    }
}
